/*
 * Newbie Contest Coding for "Nos chères configs"
 * by RaX| <raxxx.fr@gmail.com>
 *
 * This is a free software relesed as-is.
 */

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#define __DEBUG 0

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

class UserData
{

  public:

    UserData (char*);
    virtual ~UserData ();

    std::string get_name_from_index (unsigned int);
    std::string get_cpu_from_index (unsigned int);
    std::string get_ram_from_index (unsigned int);

    int get_cpu_price_from_ref (std::string);
    int get_ram_price_from_ref (std::string);

    unsigned int size ();

  private:

    std::string get_config_line ();

    int get_price_from_line (unsigned int);

    void create_array (std::string);
    void create_name_array ();
    void create_cpu_array ();
    void create_ram_array ();

    std::ifstream m_file;
    std::vector<std::string> m_config_array;
    std::vector<std::string> m_name_array;
    std::vector<std::string> m_cpu_array;
    std::vector<std::string> m_ram_array;

};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

int
main (int argc, char *argv [])
{

  if (argc < 2)
    return EXIT_FAILURE;

  UserData::UserData u_data (argv[1]);

  unsigned int best_config_price = 0;
  unsigned int best_index = 0; 
  
  for (unsigned int i = 0; i < u_data.size (); i ++)
   {
    int cpu_price = u_data.get_cpu_price_from_ref (
                      u_data.get_cpu_from_index (i)
                     );
    int ram_price = u_data.get_ram_price_from_ref (
                      u_data.get_ram_from_index (i)
                     );     

    if (cpu_price != -1 && ram_price != -1)
     {
      unsigned int current_price = cpu_price + ram_price;
      bool greater = (best_config_price < current_price);
        
      best_config_price = greater ? current_price : best_config_price;
      best_index = greater ? i : best_index;
     }

#if __DEBUG == 1
    if (cpu_price != -1 && ram_price != -1)
      std::cout << u_data.get_name_from_index (i)\
                << " "\
                << cpu_price + ram_price\
                << "€"\
                << std::endl;
    else
      std::cout << u_data.get_name_from_index (i)\
                << " "\
                << "(invalide)"\
                << std::endl;
#endif

   }

  std::cout << "http://www.newbiecontest.org/epreuves/prog/prog9/verifpr9.php?"\
                "prenom="\
            << u_data.get_name_from_index (best_index)\
            << "&prix="\
            << best_config_price\
            << std::endl;

  return EXIT_SUCCESS;

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

UserData::UserData (char *file_name) : m_file (file_name)
{

  if (!m_file.is_open ())
    exit (EXIT_FAILURE);

  create_array (get_config_line ());
  create_name_array ();
  create_cpu_array ();
  create_ram_array ();

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

std::string
UserData::get_config_line ()
{

  std::string line;

  for (int i = 0;;i++)
   {
    std::getline (m_file, line);
 
    if (i == 16 && !line.empty ())
      break;
   }

  return line;

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void
UserData::create_array (std::string str)
{

  size_t i = str.find (". ");
  size_t index_start;

  m_config_array.push_back (str.substr (0, i));

  for (;;)
   {
    index_start = i + 2;
    i = str.find (". ", i + 2);

    if (i != std::string::npos)
      m_config_array.push_back (str.substr (index_start, i - index_start));
    else
      break;
   }

#if __DEBUG == 2
  for (i = 0; i < m_config_array.size (); i++)
    std::cout << m_config_array.at (i) << std::endl;
#endif

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void
UserData::create_name_array ()
{

  unsigned int i;

  for (i = 0; i < m_config_array.size (); i++)
   {
    std::string str = m_config_array.at (i);
    m_name_array.push_back (str.substr (0, str.find (" ")));
   } 

#if __DEBUG == 3
  for (i = 0; i < m_name_array.size (); i++)
    std::cout << m_name_array.at (i) << std::endl;
#endif

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void
UserData::create_cpu_array ()
{

  unsigned int i;
 
  for (i = 0; i < m_config_array.size (); i++)
   {
    size_t index_end = m_config_array.at (i).find (" ");
    size_t index_start;
      
    for (unsigned int y = 0;; y++)
     {
      index_start = index_end + 1;
      index_end = m_config_array.at (i).find (" ", index_end + 1);

      if (y == 4)
       {
        m_cpu_array.push_back (\
          m_config_array.at (i).substr (index_start, 
                                          index_end - index_start + 4)
        );
        break;
       }
     }
   }

#if __DEBUG == 4
  for (i = 0; i < m_cpu_array.size (); i++)
    std::cout << m_cpu_array.at (i) << std::endl;
#endif

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void
UserData::create_ram_array ()
{

  unsigned int i;
 
  for (i = 0; i < m_config_array.size (); i++)
   {
    size_t index_end = m_config_array.at (i).find (" ");
    size_t index_start;

    for (unsigned int y = 0;; y++)
     {
      index_start = index_end + 1;
      index_end = m_config_array.at (i).find (" ", index_end + 1);

      if (y == 9)
       {
        m_ram_array.push_back (\
          m_config_array.at (i).substr (
            index_start, 
            m_config_array.at (i).length() - index_start)
        );
        break;
       }
     }
   }

#if __DEBUG == 5
  for (i = 0; i < m_ram_array.size (); i++)
    std::cout << m_ram_array.at (i) << std::endl;
#endif

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

std::string
UserData::get_name_from_index (unsigned int index)
{

  return m_name_array.at (index);

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

std::string
UserData::get_cpu_from_index (unsigned int index)
{

  return m_cpu_array.at (index);

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

std::string
UserData::get_ram_from_index (unsigned int index)
{

  return m_ram_array.at (index);

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

unsigned int
UserData::size ()
{

  return m_config_array.size ();

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

int
UserData::get_cpu_price_from_ref (std::string str)
{

  if (str == "166 MHz")
    return -1;
  else if (str == "433 MHz")
    return get_price_from_line (80);
  else if 	(str == "933 MHz")
    return get_price_from_line (84);
  else if 	(str == "1.0 GHz")
    return get_price_from_line (88);
  else if 	(str == "1.6 GHz")
    return get_price_from_line (92);
  else if 	(str == "1.7 GHz")
    return get_price_from_line (96);
  else if 	(str == "1.8 GHz")
    return get_price_from_line (100);
  else if 	(str == "2.4 GHz")
    return get_price_from_line (104);
  else if 	(str == "2.8 GHz")
    return get_price_from_line (108);
  else if 	(str == "3.4 GHz")
    return get_price_from_line (112);

  return -1;

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

int
UserData::get_ram_price_from_ref (std::string str)
{

  if (str == "32 Mo SDRAM")
    return get_price_from_line (29);
  else if (str == "64 Mo SDRAM")
    return get_price_from_line (33);
  else if (str == "128 Mo SDRAM")
    return get_price_from_line (37);
  else if (str == "256 Mo SDRAM")
    return get_price_from_line (41);
  else if (str == "512 Mo SDRAM")
    return get_price_from_line (45);
  else if (str == "256 Mo DDRAM")
    return get_price_from_line (49);
  else if (str == "512 Mo DDRAM")
    return get_price_from_line (53);
  else if (str == "1024 Mo DDRAM (Corsair)")
    return get_price_from_line (57);
  else if (str == "2048 Mo DDRAM (Corsair)")
    return -1;

  return -1;

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

int
UserData::get_price_from_line (unsigned int line)
{

  std::string str;
  unsigned int i;

  m_file.seekg (0);

  for (i = 0; i != line; i++)
    std::getline (m_file, str);

  i = str.find (">") + 1;

  return atoi (str.substr (i, str.find ("<", i) - i).c_str ());

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

UserData::~UserData()
{

  if (m_file.is_open ())
    m_file.close ();

}

